package server;

import java.rmi.*;
import java.rmi.registry.*;
import java.util.List;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.*;

import p2p.FileList;
import p2p.Kwalker;
import p2p.NeighborList;
import p2p.Peer;
import p2p.PeerPool;
import sun.security.util.SecurityConstants;

/**
 * RMI Server
 * @author nick
 *
 */
public class RMIServer extends java.rmi.server.UnicastRemoteObject implements Message, Serializable{
	private static final long serialVersionUID = 1L;
	private Registry registry; //RMI registry for lookup of remote objects
	private PeerPool peerPool;
	private NeighborList neighborList;
	private FileList filelist;
	private Kwalker kWalker;
	private final String name = "rmiServer";

	public RMIServer(int port, PeerPool peerPool, NeighborList neighborList, FileList filelist, Kwalker kWalker) throws RemoteException {
		this.peerPool = peerPool;
		this.neighborList = neighborList;
		this.filelist = filelist;
		this.kWalker = kWalker;
		
		try {
			(InetAddress.getLocalHost()).toString(); //ip of local host
		} catch(Exception e) {
			throw new RemoteException("Unable to receive local IP");
		}

		try {
			//create the registry and bind the name and object
			registry = LocateRegistry.createRegistry(port);
			registry.rebind(name, this);
		} catch(RemoteException e) {
			throw e;
		}
	}
	
	public void quit() {
		try {
			registry.unbind(name);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void hello(Peer fromPeer, int ttl)
			throws RemoteException, NotBoundException {
		peerPool.hello(fromPeer, ttl);		
	}

	@Override
	public void ackHello(Peer fromPeer) throws RemoteException {
		peerPool.ackHello(fromPeer);		
	}

	@Override
	public Peer helloNeighbor(Peer fromPeer)
			throws RemoteException, NotBoundException {
		return neighborList.helloNeighbor(fromPeer);		
	}

	@Override
	public List<Peer> getNeighbors() throws RemoteException {
		return neighborList.getNlist();
	}

	@Override
	public boolean isNeighbor(Peer fromPeer) throws RemoteException,
			NotBoundException {
		return neighborList.isNeighbor(fromPeer);
	}

	@Override
	public boolean reportFileList(Peer fromPeer, List<File> flist) throws RemoteException {
		return filelist.reportFileList(fromPeer, flist);
	}

	@Override
	public void isAlive() throws RemoteException {
		peerPool.isAlive();
	}

	@Override
	public void search(String fileName, int ttl, int k, Peer fromPeer, List<Peer> knownPeers, String trace) throws RemoteException {
		kWalker.doKwalker(fileName, ttl, k, fromPeer, knownPeers, trace);
	}

	@Override
	public byte[] fileUpload(String fileName) throws RemoteException {
		return kWalker.fileUpload(fileName);
	}
	
	@Override
	public void writeToTerminal(String message) throws RemoteException{
		kWalker.writeToTerminal(message);
	}
}
